<template>
  <custom-modal
    default-footer
    :visible="visible"
    :loading-ok="loadingOk"
    :title="title"
    :handle-ok="handleOk"
    class="wrap"
  >
    <a-transfer
      class="transfer"
      :data-source="dataSource"
      :target-keys="targetKeys"
      :render="(item) => item.title"
      :locale="{
        itemUnit: '项',
        itemsUnit: '项',
        notFoundContent: '列表为空'
      }"
      @change="onChange"
    >
      <template #children="{ direction, selectedKeys, onItemSelect }">
        <a-input-search
          v-if="direction === 'left'"
          v-model:value="searchValue"
          style="margin-bottom: 8px"
          placeholder="请输入搜索内容"
        />
        <a-tree
          v-if="direction === 'left'"
          v-model:expanded-keys="expandedKeys"
          block-node
          checkable
          check-strictly
          :checked-keys="[...selectedKeys, ...targetKeys]"
          :tree-data="treeData"
          @check="
            (_, props) => {
              onChecked(_, props, [...selectedKeys, ...targetKeys], onItemSelect)
            }
          "
          @select="
            (_, props) => {
              onChecked(_, props, [...selectedKeys, ...targetKeys], onItemSelect)
            }
          "
        >
          <template #title="{ title }">
            <span v-if="title.indexOf(searchValue) > -1">
              {{ title.substr(0, title.indexOf(searchValue)) }}
              <span style="color: #f50">{{ searchValue }}</span>
              {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
            </span>
            <span v-else>{{ title }}</span>
          </template>
        </a-tree>
      </template>
    </a-transfer>
  </custom-modal>
</template>

<script lang="ts">
  import { defineComponent, reactive, computed, ref, toRefs, watch } from 'vue'
  import { Tree, Transfer, Input } from 'ant-design-vue'
  import CustomModal from '@/components/CustomModal.vue'
  import { CheckEvent } from 'ant-design-vue/es/tree/Tree'

  interface TreeDataItem {
    key: string
    title: string
    disabled?: boolean
    children?: TreeDataItem[]
  }
  const tData: TreeDataItem[] = [
    { key: '1', title: '财务部' },
    {
      key: '2',
      title: '人事部',
      children: [
        { key: '21', title: '张三' },
        { key: '22', title: '李四' }
      ]
    },
    { key: '3', title: '商务部' }
  ]

  const transferDataSource: TreeDataItem[] = []
  function flatten(list: TreeDataItem[] = []) {
    list.forEach((item) => {
      transferDataSource.push(item)
      flatten(item.children)
    })
  }
  flatten(JSON.parse(JSON.stringify(tData))) // 默认穿梭框右侧是单列非树形结构，故此扁平化处理数据源

  function isChecked(selectedKeys: string[], eventKey: string) {
    return selectedKeys.indexOf(eventKey) !== -1
  }

  function handleTreeData(data: TreeDataItem[], targetKeys: string[] = []): TreeDataItem[] {
    data.forEach((item) => {
      item['disabled'] = targetKeys.includes(item.key)
      if (item.children) {
        handleTreeData(item.children, targetKeys)
      }
    })
    return data
  }
  const getParentKey = (key: string, tree: TreeDataItem[]): string | number | undefined => {
    let parentKey
    for (let i = 0; i < tree.length; i++) {
      const node = tree[i]
      if (node.children?.length) {
        if (node.children.some((item) => item.key === key)) {
          parentKey = node.key
        } else {
          getParentKey(key, node.children)
        }
      }
    }
    return parentKey
  }
  export default defineComponent({
    name: 'SelectStaff',
    components: {
      CustomModal,
      [Tree.name]: Tree,
      [Input.Search.name]: Input.Search,
      [Transfer.name]: Transfer
    },
    props: {
      title: {
        type: String,
        default: ''
      },
      modalVisible: {
        type: Boolean,
        default: false
      },
      fields: {
        type: Object,
        default: () => ({})
      }
    },
    emits: ['selectStaff'],
    setup(props, { emit }) {
      const state = reactive({
        visible: props.modalVisible,
        loadingOk: false,
        expandedKeys: Array<string>(),
        searchValue: '',
        targetKeys: Array<string>()
      })

      watch(
        () => props.modalVisible,
        (newVal) => {
          state.visible = newVal
          state.expandedKeys = []
          state.targetKeys = []
          state.searchValue = ''
        }
      )

      const handleOk = () => {
        state.visible = false
        const arr: Array<string> = []
        for (let i = 0; i < state.targetKeys.length; i++) {
          dataSource.value.some((item) => {
            if (item.key === state.targetKeys[i]) {
              arr.push(item.title)
              return true
            } else return false
          })
        }
        emit('selectStaff', arr)
      }

      const dataSource = ref<TreeDataItem[]>(transferDataSource)

      const treeData = computed<TreeDataItem[]>(() => {
        return handleTreeData(tData, state.targetKeys)
      })

      const onChange = (keys: string[]) => {
        state.targetKeys = keys
        console.log(keys)
      }
      const onChecked = (
        _: Record<string, string[]>,
        e: CheckEvent,
        checkedKeys: string[],
        onItemSelect: (n: any, c: boolean) => void
      ) => {
        const { eventKey } = e.node
        onItemSelect(eventKey, !isChecked(checkedKeys, eventKey))
      }

      watch(
        () => state.searchValue,
        (value) => {
          const expanded = dataSource.value
            .map((item: TreeDataItem) => {
              if ((item.title as string).indexOf(value) > -1) {
                return getParentKey(item.key as string, dataSource.value)
              }
              return null
            })
            .filter((item, i, self) => item && self.indexOf(item) === i)
          state.expandedKeys = expanded as string[]
          state.searchValue = value
        }
      )

      return {
        ...toRefs(state),
        handleOk,
        dataSource,
        treeData,
        onChange,
        onChecked
      }
    }
  })
</script>

<style lang="scss">
  .transfer {
    margin: 10px 0 !important;
  }
  .ant-transfer-customize-list .ant-transfer-list {
    width: 50% !important;
  }
</style>
